home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
threads
/
USpawn.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-18
|
9KB
|
402 lines
/* File: USpawn.c last edit:
* Demers 21-May-90 12:38:03
* Boehm May 29, 1991 5:12:42 pm PDT
*
* Copyright (C) 1990 by Xerox Corporation. All rights reserved.
*
* Replacement for system and popen.
*/
/* begincopyright
Copyright (c) 1988 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA
endcopyright */
#include <xr/ThreadsBackdoor.h>
#include <xr/ThreadsMsgPrivate.h>
#include <xr/UIO.h>
#include <xr/UIOPrivate.h>
#include <xr/Errno.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <string.h>
#include <sysexits.h>
/*
* The following stuff belongs in a .h file ...
*/
#undef iopo_spawnStdin
#undef iopo_spawnStdout
#undef iopo_spawnStderr
typedef int (*XR_SpawnConnectProc)(/* XR_Pointer data */);
typedef int (*XR_SpawnExecProc)(/* XR_Pointer data */);
#define iopo_spawnExecProc iopo_args[0]
/* define iopo_spawnWD iopo_args[1] */
#define iopo_spawnConnectProc iopo_args[2]
#define iopo_spawnExecClientData iopo_args[3]
#define iopo_spawnConnectClientData iopo_args[4]
/* define iopo_spawnPID iopo_args[5] */
/*
* ... end of stuff that belongs in a .h file.
*/
#define XR_spawnWaitList (XR_uioArea->uioa_spawnWaitList)
#define XR_SPAWN_DEFAULT_FILE "/dev/null"
#define XR_SPAWN_IN_OFLAGS (O_RDONLY)
#define XR_SPAWN_OUT_OFLAGS (O_WRONLY|O_CREAT|O_TRUNC)
#define XR_SPAWN_SHELL_NAME "sh"
#define XR_SPAWN_SHELL_PATH "/bin/sh"
#define XR_SPAWN_DEBUG 0
#if XR_SPAWN_DEBUG
#define CheckSpawnWaitList(m) {\
if( XR_HeadOfCycleInIOPOList(XR_spawnWaitList) != NIL ) XR_Panic(m); \
}
XR_IOPOrder
XR_HeadOfCycleInIOPOList(list)
XR_IOPOrder list;
{
XR_IOPOrder p, t;
int i;
p = t = list;
for( i = 0; ; i += 1 ) {
if( p == NIL ) return NIL;
p = p->iopo_next;
if( p == t ) break;
if( (i & 01) != 0 ) t = t->iopo_next;
}
/* given a loop containing p == t find its head */
/* find its length */
for( i = 1; t->iopo_next != p; t = t->iopo_next ) i += 1;
/* find its head */
p = list;
while( i > 0 ) { p = p->iopo_next; i -= 1; }
t = list;
while( p != t ) { p = p->iopo_next; t = t->iopo_next; }
return p;
}
#else
#define CheckSpawnWaitList(m)
#endif
static int
XR_SpawnOpen(name, flags, fd)
char *name;
int flags;
int fd;
{
int t;
if( (name == NIL) || (name[0] == 0) ) name = XR_SPAWN_DEFAULT_FILE;
t = open(name, flags, 0666);
if( t < 0 )
return( EX_DATAERR );
if( t != fd ) {
if( dup2(t, fd) != 0 )
return( EX_OSERR );
(void)close(t);
}
return(0);
}
static void
XR_SpawnedChildWorker(
wd,
connectProc, connectClientData,
execProc, execClientData
)
char *wd;
XR_SpawnConnectProc connectProc;
XR_Pointer connectClientData;
XR_SpawnExecProc execProc;
XR_Pointer execClientData;
{
extern char **environ;
char *(argv[4]);
int i, ans;
int zero = 0;
struct sigvec vec;
(void) chdir( wd ? wd : "/");
for( i = getdtablesize()-1; i >= 0; i-- ) {
(void)close(i);
}
vec.sv_handler = SIG_DFL;
vec.sv_mask = 0;
vec.sv_flags = 0;
for( i = 0; i < NSIG; i++ ) {
(void)sigvec(i, &vec, NIL);
}
(void)sigblock(0);
/*
* The following is supposed to make new pgrp / session id
* ready for new control tty in either 4.0.x or 4.1 ...
*/
if( (i = open("/dev/tty", O_WRONLY, 0)) >= 0 ) {
(void)ioctl(i, TIOCNOTTY, &zero);
(void)close(i);
}
(void)setpgrp( 0 /*=>self*/, 0 /*=>new*/ );
/* above equivalent to POSIX / 4.1: (void)setsid(); */
ans = (*connectProc)(connectClientData);
if( ans != 0 ) exit(ans);
ans = (*execProc)(execClientData);
exit(ans);
}
void
XR_SpawnIOPOrderProc (iopo)
XR_IOPOrder iopo;
/*
Result in wait->sw_pid is child PID, and wait has been
linked into waiters list.
On failure, result in wait->sw_pid is (-errno).
*/
{
# define wd ((char *)(iopo->iopo_spawnWD))
# define connectProc \
((XR_SpawnConnectProc)(iopo->iopo_spawnConnectProc))
# define connectClientData \
((XR_Pointer)(iopo->iopo_spawnConnectClientData))
# define execProc \
((XR_SpawnExecProc)(iopo->iopo_spawnExecProc))
# define execClientData \
((XR_Pointer)(iopo->iopo_spawnExecClientData))
int childID;
if( (childID = fork()) != 0 ) /* parent */ {
if( childID != -1 ) {
CheckSpawnWaitList("Check_SpawnIOPOrderProc 0");
iopo->iopo_spawnPID = childID;
iopo->iopo_next = XR_spawnWaitList;
XR_spawnWaitList = iopo;
} else {
iopo->iopo_results[0] = -(errno);
XR_NotifyIOPODone(iopo);
}
CheckSpawnWaitList("Check_SpawnIOPOrderProc 1");
return;
} else /* child */ {
XR_SpawnedChildWorker( wd, connectProc, connectClientData,
execProc, execClientData );
}
/*NOTREACHED*/
# undef cmd
# undef wd
# undef connectProc
# undef connectClientData
# undef execProc
# undef execClientData
}
void
XR_IOPSpawnChildDied()
{
union wait statusBuf;
int pid;
XR_IOPOrder p, prev;
while( (pid = wait3(&statusBuf, WNOHANG, NIL)) > 0 ) {
p = XR_spawnWaitList;
prev = NIL;
CheckSpawnWaitList("Check_IOPSpawnChildDied");
while( (p != NIL) && (p->iopo_spawnPID != pid) ) {
prev = p;
p = p->iopo_next;
}
if( p != NIL ) {
if( prev == NIL ) {
XR_spawnWaitList = p->iopo_next;
} else {
prev->iopo_next = p->iopo_next;
}
p->iopo_results[0] = statusBuf.w_status;
XR_NotifyIOPODone(p);
}
}
}
#define FixFileName(name) \
((name) ? XR_ExpandPath(XR_UIOFixStringArg(name)) : NIL)
int
XR_CDConnectSpawn(
wd, connectProc, connectClientData, execProc, execClientData
)
char *wd; /* NIL => /, "" => PCR working dir */
int ((*connectProc)());
XR_Pointer connectClientData;
int ((*execProc)());
XR_Pointer execClientData;
{
XR_IOPOrder iopo;
XR_IOPOResult res;
int status;
iopo = (XR_IOPOrder)(XR_malloc(sizeof(struct XR_IOPOrderRep)));
XR_InitIOPOrder(iopo);
iopo->iopo_spawnWD = ((unsigned)(FixFileName(wd)));
iopo->iopo_spawnConnectProc = ((unsigned)(connectProc));
iopo->iopo_spawnConnectClientData = ((unsigned)(connectClientData));
iopo->iopo_spawnExecProc = ((unsigned)(execProc));
iopo->iopo_spawnExecClientData = ((unsigned)(execClientData));
iopo->iopo_spawnPID = 0;
res = XR_IssueIOPOrder(
/*iop*/ XR_uioArea->uioa_iope,
/*order*/ iopo,
/*proc*/ XR_SpawnIOPOrderProc,
/*cancel*/ NIL,
/*abortable*/ TRUE,
/*timeout*/ XR_WAIT_FOREVER
);
switch(res) {
case XR_IOPO_RESULT_OK:
status = iopo->iopo_results[0];
if( status < 0 ) {
XR_SetErrno(-status);
return(-1);
}
return(status);
case XR_IOPO_RESULT_ABORTED:
XR_SetErrno(XR_EABORTED);
return(-1);
default:
XR_Panic("XR_Spawn 0");
}
}
typedef struct XR_SpawnFileNamesRep {
char *sfn_cmd;
char *sfn_stdin;
char *sfn_stdout;
char *sfn_stderr;
} * XR_SpawnFileNames;
static int
XR_CDSpawnConnectProc(clientData)
XR_Pointer clientData;
{
int ans;
XR_SpawnFileNames sfn = ((XR_SpawnFileNames)(clientData));
ans = XR_SpawnOpen(sfn->sfn_stdin, XR_SPAWN_IN_OFLAGS, 0);
if( ans == 0 )
ans = XR_SpawnOpen(sfn->sfn_stdout, XR_SPAWN_OUT_OFLAGS, 1);
if( ans == 0 )
ans = XR_SpawnOpen(sfn->sfn_stderr, XR_SPAWN_OUT_OFLAGS, 2);
return ans;
}
static int
XR_CDSpawnExecProc(clientData)
XR_Pointer clientData;
{
int ans;
XR_SpawnFileNames sfn = ((XR_SpawnFileNames)(clientData));
extern char **environ;
char *(argv[4]);
argv[0] = XR_SPAWN_SHELL_NAME;
argv[1] = "-c";
argv[2] = sfn->sfn_cmd;
argv[3] = NIL;
(void)execve(XR_SPAWN_SHELL_PATH, argv, environ);
/* if we get here the exec failed */
return EX_OSERR;
}
int
XR_CDSpawn(cmd, wd, stdin, stdout, stderr)
char *cmd;
char *wd; /* NIL => /, "" => PCR working dir */
char *stdin; /* NIL, "" => /dev/null */
char *stdout;
char *stderr;
{
XR_SpawnFileNames sfn;
sfn = (XR_SpawnFileNames) XR_malloc(sizeof(struct XR_SpawnFileNamesRep));
sfn->sfn_cmd = XR_UIOFixStringArg(cmd);
sfn->sfn_stdin = FixFileName(stdin);
sfn->sfn_stdout = FixFileName(stdout);
sfn->sfn_stderr = FixFileName(stderr);
return XR_CDConnectSpawn( wd, XR_CDSpawnConnectProc, sfn,
XR_CDSpawnExecProc, sfn );
}
int
XR_Spawn(cmd, stdin, stdout, stderr)
char *cmd;
char *stdin; /* NIL, "" => /dev/null */
char *stdout;
char *stderr;
{
return XR_CDSpawn(cmd, "", stdin, stdout, stderr);
}
/* LOG
21-May-90 12:41:25 - Demers - Created
USpawn.c 1.1 of 5/22/90
@(#)USpawn.c 1.1
*/